Client and Subscriber Development > Extensions > Integrated Extensions > OPC UA Complex Data Extension > Advanced OPC UA Complex Data Tasks > Navigation in the OPC UA data model |
For accessing the metadata about data types in OPC UA and navigating in it, the OPC UA Complex Data extension gives you
The providers retrieve the information from the OPC server in various ways (by reading and browsing the metadata nodes). In addition, they cache the information obtained. This is very important for performance reasons, because the same metadata can be reused without having to retrieve them from the server again and again.
Take following steps to get access to the OPC UA data type model provider:
When you have the IUADataTypeModelProvider Interface, you can call its methods to:
The basic methods on the IUADataTypeModelProvider Interface provide just one navigation "hop" at a time. Some of these "hops" are, however, commonly needed together, in a chain, possibly with some kind of additional simple processing. For this purpose, there are extension methods available (in the IUADataTypeModelProviderExtension Class) that make such tasks easier. With help of these methods, you can then, for example:
If you have more pieces of information to work on in the same way, it is much more efficient to process them together, in one operation. All methods on the IUADataTypeModelProvider Interface and the IUADataTypeModelProviderExtension Class therefore accept a read-only list on input, and return an array of processed element on the output. If performance is not a concern, or if you have just one piece of information to work on at a time, there are extension methods to make it easier as well. For example, instead of calling GetDataTypeIdsFromModelNodeDescriptors Method for just one node, you can use the GetDataTypeIdFromModelNodeDescriptor Method instead.
Take following steps to get access to the OPC UA data type dictionary provider:
When you have the IUADataTypeDictionaryProvider Interface, you can call its methods to:
The basic methods on the IUADataTypeDictionaryProvider Interface provide just one navigation "hop" at a time. Some of these "hops" are, however, commonly needed together, in a chain, possibly with some kind of additional simple processing. For this purpose, there are extension methods available (in the IUADataTypeDictionaryProviderExtension Class) that make such tasks easier. With help of these methods, you can then, for example:
If you have more pieces of information to work on in the same way, it is much more efficient to process them together, in one operation. All methods on the IUADataTypeDictionaryProvider Interface and the IUADataTypeDictionaryProviderExtension Class therefore accept a read-only list on input, and return an array of processed element on the output. If performance is not a concern, or if you have just one piece of information to work on at a time, there are extension methods to make it easier as well.
Take following steps to get access to the OPC UA data type dictionary provider:
When you have the IUADataTypeDefinitionProvider Interface, you can call its methods to:
If you have more pieces of information to work on in the same way, it is much more efficient to process them together, in one operation. All methods on the IUADataTypeDictionaryProvider Interface therefore accept a read-only list on input, and return an array of processed element on the output. If performance is not a concern, or if you have just one piece of information to work on at a time, there are extension methods in the IUADataTypeDefinitionProviderExtension Class to make it easier as well.
When you receive complex data in the GenericData Property of a UAGenericObject, it has its DataType Property filled in with information about the associated data type, so that you can process it as you need. But what you have not yet received the complex data from the server - maybe you are just preparing something to be written, and you want to inspect what is the data type structure for certain node or data type ID? In this case, you can use the methods on the IUADataTypeModelProvider Interface to obtain an instance of DataType Class.
The example below shows how to resolve a data type. The main work is done by the ResolveDataType Method.
// Shows how to obtain object describing the data type of complex data node with OPC UA Complex Data plug-in. // // Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html . using System; using Microsoft.Extensions.DependencyInjection; using OpcLabs.BaseLib.DataTypeModel; using OpcLabs.BaseLib.OperationModel.Generic; using OpcLabs.EasyOpc.UA; using OpcLabs.EasyOpc.UA.AddressSpace; using OpcLabs.EasyOpc.UA.AddressSpace.Standard; using OpcLabs.EasyOpc.UA.InformationModel; using OpcLabs.EasyOpc.UA.Plugins.ComplexData; namespace UADocExamples.ComplexData._IEasyUAClientComplexData { class ResolveDataType { public static void Main1() { // Define which server we will work with. UAEndpointDescriptor endpointDescriptor = "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"; // or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported) // or "https://opcua.demo-this.com:51212/UA/SampleServer/" // Instantiate the client object. var client = new EasyUAClient(); // Obtain the data type ID. // // In many cases, you would be able to obtain the data type ID of a particular node by reading its DataType // attribute, or easier, by calling the extension method ReadDataType on the IEasyUAClient interface. // The sample server, however, shows a more advanced approach in which the data type ID refers to an abstract // data type, and the actual values are then sub-types of this base data type. This abstract data type does not // have any encodings associated with it and it is therefore not possible to extract its description from the // server. We therefore use a hard-coded data type ID for one of the sub-types in this example. // // The code to obtain the data type ID for given node would normally look like this: // UANodeId dataTypeId = client.ReadDataType( // endpointDescriptor, // "nsu=http://test.org/UA/Data/ ;i=10239"); // [ObjectsFolder]/Data.Static.Scalar.StructureValue // UANodeId dataTypeId = "nsu=http://test.org/UA/Data/ ;i=9440"; // ScalarValueDataType // Get the IEasyUAClientComplexData service from the client. This is needed for advanced complex data // operations. IEasyUAClientComplexData complexData = client.GetService<IEasyUAClientComplexData>(); // Resolve the data type ID to the data type object, containing description of the data type. ValueResult<DataType> dataTypeResult = complexData.ResolveDataType( new UAModelNodeDescriptor(endpointDescriptor, dataTypeId), UABrowseNames.DefaultBinary); // Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown. if (!dataTypeResult.Succeeded) { Console.WriteLine("*** Failure: {0}", dataTypeResult.ErrorMessageBrief); return; } // The actual data type is in the Value property. // Display basic information about what we have obtained. Console.WriteLine(dataTypeResult.Value); // If we want to see the whole hierarchy of the received data type, we can format it with the "V" (verbose) // specifier. In the debugger, you can view the same by displaying the private DebugView property. Console.WriteLine(); Console.WriteLine("{0:V}", dataTypeResult.Value); // For processing the internals of the data type, refer to examples for GenericData class. // Example output (truncated): // //ScalarValueDataType = structured // //ScalarValueDataType = structured // [BooleanValue] Boolean = primitive(System.Boolean) // [ByteStringValue] ByteString = primitive(System.Byte[]) // [ByteValue] Byte = primitive(System.Byte) // [DateTimeValue] DateTime = primitive(System.DateTime) // [DoubleValue] Double = primitive(System.Double) // [EnumerationValue] Int32 = primitive(System.Int32) // [ExpandedNodeIdValue] ExpandedNodeId = structured // [ByteString] optional ByteStringNodeId = structured // [Identifier] ByteString = primitive(System.Byte[]) // [NamespaceIndex] UInt16 = primitive(System.UInt16) // [FourByte] optional FourByteNodeId = structured // [Identifier] UInt16 = primitive(System.UInt16) // [NamespaceIndex] Byte = primitive(System.Byte) // [Guid] optional GuidNodeId = structured // [Identifier] Guid = primitive(System.Guid) // [NamespaceIndex] UInt16 = primitive(System.UInt16) // [NamespaceURI] optional CharArray = primitive(System.String) // [NamespaceURISpecified] switch Bit = primitive(System.Boolean) // [NodeIdType] switch NodeIdType = enumeration(6) // TwoByte = 0 // FourByte = 1 // Numeric = 2 // String = 3 // Guid = 4 // ByteString = 5 // [Numeric] optional NumericNodeId = structured // [Identifier] UInt32 = primitive(System.UInt32) // [NamespaceIndex] UInt16 = primitive(System.UInt16) // [ServerIndex] optional UInt32 = primitive(System.UInt32) // [ServerIndexSpecified] switch Bit = primitive(System.Boolean) // [String] optional StringNodeId = structured // [Identifier] CharArray = primitive(System.String) // [NamespaceIndex] UInt16 = primitive(System.UInt16) // [TwoByte] optional TwoByteNodeId = structured // [Identifier] Byte = primitive(System.Byte) // [FloatValue] Float = primitive(System.Single) // [GuidValue] Guid = primitive(System.Guid) // [Int16Value] Int16 = primitive(System.Int16) // [Int32Value] Int32 = primitive(System.Int32) // [Int64Value] Int64 = primitive(System.Int64) // [Integer] Variant = structured // [ArrayDimensions] optional sequence[*] of Int32 = primitive(System.Int32) // [ArrayDimensionsSpecified] switch sequence[1] of Bit = primitive(System.Boolean) // [ArrayLength] length optional Int32 = primitive(System.Int32) // [ArrayLengthSpecified] switch sequence[1] of Bit = primitive(System.Boolean) // [Boolean] optional sequence[*] of Boolean = primitive(System.Boolean) // [Byte] optional sequence[*] of Byte = primitive(System.Byte) } } }
# Shows how to obtain object describing the data type of complex data node with OPC UA Complex Data plug-in. # # Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html . # OPC client and subscriber examples in Python on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-Python . # The QuickOPC package is needed. Install it using "pip install opclabs_quickopc". import opclabs_quickopc # Import .NET namespaces. from Microsoft.Extensions.DependencyInjection import * from System import * from OpcLabs.EasyOpc.UA import * from OpcLabs.EasyOpc.UA.AddressSpace import * from OpcLabs.EasyOpc.UA.AddressSpace.Standard import * #from OpcLabs.EasyOpc.UA.Extensions import * from OpcLabs.EasyOpc.UA.InformationModel import * from OpcLabs.EasyOpc.UA.Plugins.ComplexData import * endpointDescriptor = UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:51210/UA/SampleServer') # or 'http://opcua.demo-this.com:51211/UA/SampleServer' (currently not supported) # or 'https://opcua.demo-this.com:51212/UA/SampleServer/' # Instantiate the client object. client = EasyUAClient() # Obtain the data type ID. # # In many cases, you would be able to obtain the data type ID of a particular node by reading its DataType # attribute, or easier, by calling the extension method ReadDataType on the IEasyUAClient interface. # The sample server, however, shows a more advanced approach in which the data type ID refers to an abstract # data type, and the actual values are then sub-types of this base data type. This abstract data type does not # have any encodings associated with it and it is therefore not possible to extract its description from the # server. We therefore use a hard-coded data type ID for one of the sub-types in this example. # # The code to obtain the data type ID for given node would normally look like this: # dataTypeId = IEasyUAClientExtension2.ReadDataType(client, # endpointDescriptor, # UANodeDescriptor('nsu=http://test.org/UA/Data/ ;i=10239')) # [ObjectsFolder]/Data.Static.Scalar.StructureValue dataTypeId = UANodeId('nsu=http://test.org/UA/Data/ ;i=9440') # ScalarValueDataType # Get the IEasyUAClientComplexData service from the client. This is needed for advanced complex data # operations. complexData = ServiceProviderServiceExtensions.GetService[IEasyUAClientComplexData](client) if complexData is None: print('The client complex data service is not available.') exit() # Resolve the data type ID to the data type object, containing description of the data type. dataTypeResult = IEasyUAClientComplexDataExtension.ResolveDataType(complexData, UAModelNodeDescriptor(endpointDescriptor, UANodeDescriptor(dataTypeId)), UABrowseNames.DefaultBinary) # Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown. if not dataTypeResult.Succeeded: print('*** Failure: ', dataTypeResult.ErrorMessageBrief) exit() # The actual data type is in the Value property. # Display basic information about what we have obtained. print(dataTypeResult.Value) # If we want to see the whole hierarchy of the received data type, we can format it with the "V" (verbose) # specifier. In the debugger, you can view the same by displaying the private DebugView property. print() print(String.Format('{0:V}', dataTypeResult.Value)) # For processing the internals of the data type, refer to examples for GenericData class. print() print('Finished.')
' Shows how to obtain object describing the data type of complex data node with OPC UA Complex Data plug-in. ' ' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html . Imports System Imports Microsoft.Extensions.DependencyInjection Imports OpcLabs.BaseLib.DataTypeModel Imports OpcLabs.BaseLib.OperationModel.Generic Imports OpcLabs.EasyOpc.UA Imports OpcLabs.EasyOpc.UA.AddressSpace Imports OpcLabs.EasyOpc.UA.AddressSpace.Standard Imports OpcLabs.EasyOpc.UA.InformationModel Imports OpcLabs.EasyOpc.UA.Plugins.ComplexData Namespace ComplexData._IEasyUAClientComplexData Friend Class ResolveDataType Public Shared Sub Main1() ' Define which server we will work with. Dim endpointDescriptor As UAEndpointDescriptor = "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer" ' or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported) ' or "https://opcua.demo-this.com:51212/UA/SampleServer/" ' Instantiate the client object. Dim client = New EasyUAClient ' Obtain the data type ID. ' ' In many cases, you would be able to obtain the data type ID of a particular node by reading its DataType ' attribute, or easier, by calling the extension method ReadDataType on the IEasyUAClient interface. The sample ' server, however, shows a more advanced approach in which the data type ID refers to an abstract data type, ' and the actual values are then sub-types of this base data type. This abstract data type does not have any ' encodings associated with it and it is therefore not possible to extract its description from the server. ' We therefore use a hard-coded data type ID for one of the sub-types in this example. ' ' The code to obtain the data type ID for given node would normally look like this: ' UANodeId dataTypeId = client.ReadDataType( ' endpointDescriptor, ' "nsu=http://test.org/UA/Data/ ;i=10239"); // [ObjectsFolder]/Data.Static.Scalar.StructureValue ' Dim dataTypeId As UANodeId = "nsu=http://test.org/UA/Data/ ;i=9440" ' ScalarValueDataType ' Get the IEasyUAClientComplexData service from the client. This is needed for advanced complex data ' operations. Dim complexData As IEasyUAClientComplexData = client.GetService(Of IEasyUAClientComplexData) ' Resolve the data type ID to the data type object, containing description of the data type. Dim dataTypeResult As ValueResult(Of DataType) = complexData.ResolveDataType( _ New UAModelNodeDescriptor(endpointDescriptor, dataTypeId), _ UABrowseNames.DefaultBinary) ' Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown. If Not dataTypeResult.Succeeded Then Console.WriteLine("*** Failure: {0}", dataTypeResult.ErrorMessageBrief) Exit Sub End If ' The actual data type is in the Value property. ' Display basic information about what we have obtained. Console.WriteLine(dataTypeResult.Value) ' If we want to see the whole hierarchy of the received data type, we can format it with the "V" (verbose) ' specifier. In the debugger, you can view the same by displaying the private DebugView property. Console.WriteLine() Console.WriteLine("{0:V}", dataTypeResult.Value) ' For processing the internals of the data type, refer to examples for GenericData class. ' Example output (truncated): ' 'ScalarValueDataType = structured ' 'ScalarValueDataType = structured ' [BooleanValue] Boolean = primitive(System.Boolean) ' [ByteStringValue] ByteString = primitive(System.Byte[]) ' [ByteValue] Byte = primitive(System.Byte) ' [DateTimeValue] DateTime = primitive(System.DateTime) ' [DoubleValue] Double = primitive(System.Double) ' [EnumerationValue] Int32 = primitive(System.Int32) ' [ExpandedNodeIdValue] ExpandedNodeId = structured ' [ByteString] optional ByteStringNodeId = structured ' [Identifier] ByteString = primitive(System.Byte[]) ' [NamespaceIndex] UInt16 = primitive(System.UInt16) ' [FourByte] optional FourByteNodeId = structured ' [Identifier] UInt16 = primitive(System.UInt16) ' [NamespaceIndex] Byte = primitive(System.Byte) ' [Guid] optional GuidNodeId = structured ' [Identifier] Guid = primitive(System.Guid) ' [NamespaceIndex] UInt16 = primitive(System.UInt16) ' [NamespaceURI] optional CharArray = primitive(System.String) ' [NamespaceURISpecified] switch Bit = primitive(System.Boolean) ' [NodeIdType] switch NodeIdType = enumeration(6) ' TwoByte = 0 ' FourByte = 1 ' Numeric = 2 ' String = 3 ' Guid = 4 ' ByteString = 5 ' [Numeric] optional NumericNodeId = structured ' [Identifier] UInt32 = primitive(System.UInt32) ' [NamespaceIndex] UInt16 = primitive(System.UInt16) ' [ServerIndex] optional UInt32 = primitive(System.UInt32) ' [ServerIndexSpecified] switch Bit = primitive(System.Boolean) ' [String] optional StringNodeId = structured ' [Identifier] CharArray = primitive(System.String) ' [NamespaceIndex] UInt16 = primitive(System.UInt16) ' [TwoByte] optional TwoByteNodeId = structured ' [Identifier] Byte = primitive(System.Byte) ' [FloatValue] Float = primitive(System.Single) ' [GuidValue] Guid = primitive(System.Guid) ' [Int16Value] Int16 = primitive(System.Int16) ' [Int32Value] Int32 = primitive(System.Int32) ' [Int64Value] Int64 = primitive(System.Int64) ' [Integer] Variant = structured ' [ArrayDimensions] optional sequence[*] of Int32 = primitive(System.Int32) ' [ArrayDimensionsSpecified] switch sequence[1] of Bit = primitive(System.Boolean) ' [ArrayLength] length optional Int32 = primitive(System.Int32) ' [ArrayLengthSpecified] switch sequence[1] of Bit = primitive(System.Boolean) ' [Boolean] optional sequence[*] of Boolean = primitive(System.Boolean) ' [Byte] optional sequence[*] of Byte = primitive(System.Byte) End Sub End Class End Namespace
// Shows how to obtain object describing the data type of complex data node with OPC UA Complex Data plug-in. // // Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html . class procedure ResolveDataType.Main; var Client: _EasyUAClient; ComplexData: _EasyUAClientComplexData; DataType: _DataType; DataTypeId: string; DataTypeResult: _ValueResult; EncodingName: _UAQualifiedName; EndpointDescriptor: string; ModelNodeDescriptor: _UAModelNodeDescriptor; begin // Define which server and node we will work with. EndpointDescriptor := //'http://opcua.demo-this.com:51211/UA/SampleServer'; //'https://opcua.demo-this.com:51212/UA/SampleServer/'; 'opc.tcp://opcua.demo-this.com:51210/UA/SampleServer'; // Instantiate the client object Client := CoEasyUAClient.Create; // Obtain the data type ID. // // In many cases, you would be able to obtain the data type ID of a particular node by reading its DataType // attribute. // The sample server, however, shows a more advanced approach in which the data type ID refers to an abstract data type, and // the actual values are then sub-types of this base data type. This abstract data type does not have any encodings // associated with it and it is therefore not possible to extract its description from the server. We therefore use // a hard-coded data type ID for one of the sub-types in this example. DataTypeId := 'nsu=http://test.org/UA/Data/ ;i=9440'; // ScalarValueDataType // Get the IEasyUAClientComplexData service from the client. This is needed for advanced complex data // operations. ComplexData := IInterface(Client.GetServiceByName('OpcLabs.EasyOpc.UA.Plugins.ComplexData.IEasyUAClientComplexData, OpcLabs.EasyOpcUA')) as _EasyUAClientComplexData; // Resolve the data type ID to the data type object, containing description of the data type. ModelNodeDescriptor := CoUAModelNodeDescriptor.Create; ModelNodeDescriptor.EndpointDescriptor.UrlString := EndpointDescriptor; ModelNodeDescriptor.NodeDescriptor.NodeId.ExpandedText := DataTypeId; EncodingName := CoUAQualifiedName.Create; EncodingName.StandardName := 'DefaultBinary'; DataTypeResult := ComplexData.ResolveDataType(ModelNodeDescriptor, EncodingName); if not DataTypeResult.Succeeded then begin WriteLn(Format('*** Failure: %s', [DataTypeResult.ErrorMessageBrief])); Exit; end; // The actual data type is in the Value property. DataType := IUnknown(DataTypeResult.Value) as _DataType; // Display basic information about what we have obtained. WriteLn(DataType.ToString); // If we want to see the whole hierarchy of the received data type, we can format it with the "V" (verbose) // specifier. Writeln; Writeln(DataType.ToString_2['V', nil]); // For processing the internals of the data type, refer to examples for GenericData class. // Example output (truncated): // //ScalarValueDataType = structured // //ScalarValueDataType = structured // [BooleanValue] Boolean = primitive(System.Boolean) // [ByteStringValue] ByteString = primitive(System.Byte[]) // [ByteValue] Byte = primitive(System.Byte) // [DateTimeValue] DateTime = primitive(System.DateTime) // [DoubleValue] Double = primitive(System.Double) // [EnumerationValue] Int32 = primitive(System.Int32) // [ExpandedNodeIdValue] ExpandedNodeId = structured // [ByteString] optional ByteStringNodeId = structured // [Identifier] ByteString = primitive(System.Byte[]) // [NamespaceIndex] UInt16 = primitive(System.UInt16) // [FourByte] optional FourByteNodeId = structured // [Identifier] UInt16 = primitive(System.UInt16) // [NamespaceIndex] Byte = primitive(System.Byte) // [Guid] optional GuidNodeId = structured // [Identifier] Guid = primitive(System.Guid) // [NamespaceIndex] UInt16 = primitive(System.UInt16) // [NamespaceURI] optional CharArray = primitive(System.String) // [NamespaceURISpecified] switch Bit = primitive(System.Boolean) // [NodeIdType] switch NodeIdType = enumeration(6) // TwoByte = 0 // FourByte = 1 // Numeric = 2 // String = 3 // Guid = 4 // ByteString = 5 // [Numeric] optional NumericNodeId = structured // [Identifier] UInt32 = primitive(System.UInt32) // [NamespaceIndex] UInt16 = primitive(System.UInt16) // [ServerIndex] optional UInt32 = primitive(System.UInt32) // [ServerIndexSpecified] switch Bit = primitive(System.Boolean) // [String] optional StringNodeId = structured // [Identifier] CharArray = primitive(System.String) // [NamespaceIndex] UInt16 = primitive(System.UInt16) // [TwoByte] optional TwoByteNodeId = structured // [Identifier] Byte = primitive(System.Byte) // [FloatValue] Float = primitive(System.Single) // [GuidValue] Guid = primitive(System.Guid) // [Int16Value] Int16 = primitive(System.Int16) // [Int32Value] Int32 = primitive(System.Int32) // [Int64Value] Int64 = primitive(System.Int64) // [Integer] Variant = structured // [ArrayDimensions] optional sequence[*] of Int32 = primitive(System.Int32) // [ArrayDimensionsSpecified] switch sequence[1] of Bit = primitive(System.Boolean) // [ArrayLength] length optional Int32 = primitive(System.Int32) // [ArrayLengthSpecified] switch sequence[1] of Bit = primitive(System.Boolean) // [Boolean] optional sequence[*] of Boolean = primitive(System.Boolean) // [Byte] optional sequence[*] of Byte = primitive(System.Byte) end;
Rem Shows how to obtain object describing the data type of complex data node with OPC UA Complex Data plug-in. Rem Rem Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html . Option Explicit ' Define which server we will work with. Dim endpointDescriptor: endpointDescriptor = _ "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer" '"http://opcua.demo-this.com:51211/UA/SampleServer" '"https://opcua.demo-this.com:51212/UA/SampleServer/" ' Instantiate the client object. Dim Client: Set Client = CreateObject("OpcLabs.EasyOpc.UA.EasyUAClient") ' Obtain the data type ID. ' ' In many cases, you would be able to obtain the data type ID of a particular node by reading its DataType ' attribute. ' The sample server, however, shows a more advanced approach in which the data type ID refers to an abstract data type, and ' the actual values are then sub-types of this base data type. This abstract data type does not have any encodings ' associated with it and it is therefore not possible to extract its description from the server. We therefore use ' a hard-coded data type ID for one of the sub-types in this example. Dim dataTypeId: dataTypeId = "nsu=http://test.org/UA/Data/ ;i=9440" ' ScalarValueDataType ' Get the IEasyUAClientComplexData service from the client. This is needed for advanced complex data ' operations. Dim ComplexData: Set ComplexData = _ Client.GetServiceByName("OpcLabs.EasyOpc.UA.Plugins.ComplexData.IEasyUAClientComplexData, OpcLabs.EasyOpcUA") ' Resolve the data type ID to the data type object, containing description of the data type. Dim ModelNodeDescriptor: Set ModelNodeDescriptor = CreateObject("OpcLabs.EasyOpc.UA.InformationModel.UAModelNodeDescriptor") ModelNodeDescriptor.EndpointDescriptor.UrlString = endpointDescriptor ModelNodeDescriptor.NodeDescriptor.NodeId.ExpandedText = dataTypeId Dim EncodingName: Set EncodingName = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UAQualifiedName") EncodingName.StandardName = "DefaultBinary" Dim DataTypeResult: Set DataTypeResult = ComplexData.ResolveDataType(ModelNodeDescriptor, EncodingName) If Not DataTypeResult.Succeeded Then WScript.Echo "*** Failure: " & DataTypeResult.Exception.GetBaseException().Message WScript.Quit End If ' The actual data type is in the Value property. Dim DataType: Set DataType = DataTypeResult.Value ' Display basic information about what we have obtained. WScript.Echo DataType ' If we want to see the whole hierarchy of the received data type, we can format it with the "V" (verbose) ' specifier. WScript.Echo WScript.Echo DataType.ToString_2("V", Nothing) ' For processing the internals of the data type, refer to examples for GenericData class. ' Example output (truncated): ' 'ScalarValueDataType = structured ' 'ScalarValueDataType = structured ' [BooleanValue] Boolean = primitive(System.Boolean) ' [ByteStringValue] ByteString = primitive(System.Byte[]) ' [ByteValue] Byte = primitive(System.Byte) ' [DateTimeValue] DateTime = primitive(System.DateTime) ' [DoubleValue] Double = primitive(System.Double) ' [EnumerationValue] Int32 = primitive(System.Int32) ' [ExpandedNodeIdValue] ExpandedNodeId = structured ' [ByteString] optional ByteStringNodeId = structured ' [Identifier] ByteString = primitive(System.Byte[]) ' [NamespaceIndex] UInt16 = primitive(System.UInt16) ' [FourByte] optional FourByteNodeId = structured ' [Identifier] UInt16 = primitive(System.UInt16) ' [NamespaceIndex] Byte = primitive(System.Byte) ' [Guid] optional GuidNodeId = structured ' [Identifier] Guid = primitive(System.Guid) ' [NamespaceIndex] UInt16 = primitive(System.UInt16) ' [NamespaceURI] optional CharArray = primitive(System.String) ' [NamespaceURISpecified] switch Bit = primitive(System.Boolean) ' [NodeIdType] switch NodeIdType = enumeration(6) ' TwoByte = 0 ' FourByte = 1 ' Numeric = 2 ' String = 3 ' Guid = 4 ' ByteString = 5 ' [Numeric] optional NumericNodeId = structured ' [Identifier] UInt32 = primitive(System.UInt32) ' [NamespaceIndex] UInt16 = primitive(System.UInt16) ' [ServerIndex] optional UInt32 = primitive(System.UInt32) ' [ServerIndexSpecified] switch Bit = primitive(System.Boolean) ' [String] optional StringNodeId = structured ' [Identifier] CharArray = primitive(System.String) ' [NamespaceIndex] UInt16 = primitive(System.UInt16) ' [TwoByte] optional TwoByteNodeId = structured ' [Identifier] Byte = primitive(System.Byte) ' [FloatValue] Float = primitive(System.Single) ' [GuidValue] Guid = primitive(System.Guid) ' [Int16Value] Int16 = primitive(System.Int16) ' [Int32Value] Int32 = primitive(System.Int32) ' [Int64Value] Int64 = primitive(System.Int64) ' [Integer] Variant = structured ' [ArrayDimensions] optional sequence[*] of Int32 = primitive(System.Int32) ' [ArrayDimensionsSpecified] switch sequence[1] of Bit = primitive(System.Boolean) ' [ArrayLength] length optional Int32 = primitive(System.Int32) ' [ArrayLengthSpecified] switch sequence[1] of Bit = primitive(System.Boolean) ' [Boolean] optional sequence[*] of Boolean = primitive(System.Boolean) ' [Byte] optional sequence[*] of Byte = primitive(System.Byte)
You may sometimes need to view the actual content of the data type dictionary that resides in the OPC server. In itself, this is easy: The data type dictionary is in a node, so you just read the node. But, how do you find out which node to read? Here is where the IUADataTypeModelProvider Interface or the IUADataTypeDictionaryProvider Interface can help. They have methods to navigate from the node you want to access (read, write, or subscribe to) to the data type dictionary. Or, they have similar methods if you know the data type ID of the data type you are interested in. The example below shows the steps necessary.
// Shows how to obtain data type description object for complex data node with OPC UA Complex Data plug-in, and the actual // content of the data type dictionary. // // Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html . using System; using System.Text; using Microsoft.Extensions.DependencyInjection; using OpcLabs.BaseLib.OperationModel.Generic; using OpcLabs.EasyOpc.UA; using OpcLabs.EasyOpc.UA.AddressSpace; using OpcLabs.EasyOpc.UA.AddressSpace.Standard; using OpcLabs.EasyOpc.UA.DataTypeModel; using OpcLabs.EasyOpc.UA.DataTypeModel.Extensions; using OpcLabs.EasyOpc.UA.InformationModel; using OpcLabs.EasyOpc.UA.Plugins.ComplexData; namespace UADocExamples.ComplexData._IUADataTypeDictionaryProvider { class ResolveDataTypeDescriptorFromDataTypeEncodingId { public static void Main1() { // Define which server we will work with. UAEndpointDescriptor endpointDescriptor = "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"; // or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported) // or "https://opcua.demo-this.com:51212/UA/SampleServer/" // Instantiate the client object. var client = new EasyUAClient(); // Obtain the data type ID. // // In many cases, you would be able to obtain the data type ID of a particular node by reading its DataType // attribute, or easier, by calling the extension method ReadDataType on the IEasyUAClient interface. The sample // server, however, shows a more advanced approach in which the data type ID refers to an abstract data type, // and the actual values are then sub-types of this base data type. This abstract data type does not have any // encodings associated with it and it is therefore not possible to extract its description from the server. // We therefore use a hard-coded data type ID for one of the sub-types in this example. // // The code to obtain the data type ID for given node would normally look like this: // UANodeId dataTypeId = client.ReadDataType( // endpointUriString, // "nsu=http://test.org/UA/Data/ ;i=10239"); // [ObjectsFolder]/Data.Static.Scalar.StructureValue // UANodeId dataTypeId = "nsu=http://test.org/UA/Data/ ;i=9440"; // ScalarValueDataType // Get the IEasyUAClientComplexData service from the client. This is needed for advanced complex data // operations. IEasyUAClientComplexData complexData = client.GetService<IEasyUAClientComplexData>(); // Get the data type model provider. Provides methods to access data types in OPC UA model. IUADataTypeModelProvider dataTypeModelProvider = complexData.DataTypeModelProvider; // Resolve the data type ID from our data type ID, for encoding name "Default Binary". ValueResult<UAModelNodeDescriptor> encodingIdResult = dataTypeModelProvider.ResolveEncodingIdFromDataTypeId( new UAModelNodeDescriptor(endpointDescriptor, dataTypeId), UABrowseNames.DefaultBinary); // Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown. if (!encodingIdResult.Succeeded) { Console.WriteLine("*** Failure: {0}", encodingIdResult.ErrorMessageBrief); return; } UAModelNodeDescriptor encodingId = encodingIdResult.Value; // Get the data type dictionary provider. Provides methods to access data type dictionaries in OPC UA model. IUADataTypeDictionaryProvider dataTypeDictionaryProvider = complexData.DataTypeDictionaryProvider; // Resolve the data type descriptor from the encoding ID. ValueResult<UADataTypeDescriptor> dataTypeDescriptorResult = dataTypeDictionaryProvider.ResolveDataTypeDescriptorFromDataTypeEncodingId(encodingId); // Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown. if (!dataTypeDescriptorResult.Succeeded) { Console.WriteLine("*** Failure: {0}", dataTypeDescriptorResult.ErrorMessageBrief); return; } UADataTypeDescriptor dataTypeDescriptor = dataTypeDescriptorResult.Value; // The data type descriptor contains two pieces of information: // The data type dictionary ID: This determines the dictionary where the data type is defined. Console.WriteLine(dataTypeDescriptor.DataTypeDictionaryId); // And the data type description: It is a "pointer" into the data type dictionary itself, selecting a specific // type definition inside the data type dictionary. The format of it depends on the data type system; // in our case, it is a string that is the name of one of the type elements in the XML document of the data type // dictionary. Console.WriteLine(dataTypeDescriptor.DataTypeDescription); // Obtain the actual content of the data type dictionary. ValueResult<byte[]> dataTypeDictionaryResult = dataTypeDictionaryProvider.GetDataTypeDictionaryFromDataTypeDictionaryId(dataTypeDescriptor.DataTypeDictionaryId); // Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown. if (!dataTypeDictionaryResult.Succeeded) { Console.WriteLine("*** Failure: {0}", dataTypeDictionaryResult.ErrorMessageBrief); return; } byte[] dataTypeDictionary = dataTypeDictionaryResult.Value; // The data type dictionary returned is an array of bytes; its syntax and semantics depends on the data type // system. In our case, we know that the data type dictionary is actually a string encoded in UTF-8. string text = Encoding.UTF8.GetString(dataTypeDictionary); Console.WriteLine(); Console.WriteLine(text); // Example output (truncated): // //http://opcua.demo-this.com:51211/UA/SampleServer; NodeId="nsu=http://test.org/UA/Data/ ;ns=2;i=11422" //ScalarValueDataType // //<opc:TypeDictionary // xmlns:opc="http://opcfoundation.org/BinarySchema/" // xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" // xmlns:ua="http://opcfoundation.org/UA/" // xmlns:tns="http://test.org/UA/Data/" // DefaultByteOrder="LittleEndian" // TargetNamespace="http://test.org/UA/Data/" //> // <!-- This File was generated on 2013-01-22 and supports the specifications supported by version 1.1.334.0 of the OPC UA deliverables. --> // <opc:Import Namespace="http://opcfoundation.org/UA/" Location="Opc.Ua.BinarySchema.bsd"/> // // <opc:StructuredType Name="ScalarValueDataType" BaseType="ua:ExtensionObject"> // <opc:Field Name="BooleanValue" TypeName="opc:Boolean" /> // <opc:Field Name="SByteValue" TypeName="opc:SByte" /> // <opc:Field Name="ByteValue" TypeName="opc:Byte" /> // <opc:Field Name="Int16Value" TypeName="opc:Int16" /> // <opc:Field Name="UInt16Value" TypeName="opc:UInt16" /> // <opc:Field Name="Int32Value" TypeName="opc:Int32" /> // <opc:Field Name="UInt32Value" TypeName="opc:UInt32" /> // <opc:Field Name="Int64Value" TypeName="opc:Int64" /> // <opc:Field Name="UInt64Value" TypeName="opc:UInt64" /> // <opc:Field Name="FloatValue" TypeName="opc:Float" /> // <opc:Field Name="DoubleValue" TypeName="opc:Double" /> // <opc:Field Name="StringValue" TypeName="opc:String" /> // <opc:Field Name="DateTimeValue" TypeName="opc:DateTime" /> // <opc:Field Name="GuidValue" TypeName="opc:Guid" /> // <opc:Field Name="ByteStringValue" TypeName="opc:ByteString" /> // <opc:Field Name="XmlElementValue" TypeName="ua:XmlElement" /> // <opc:Field Name="NodeIdValue" TypeName="ua:NodeId" /> // <opc:Field Name="ExpandedNodeIdValue" TypeName="ua:ExpandedNodeId" /> // <opc:Field Name="QualifiedNameValue" TypeName="ua:QualifiedName" /> // <opc:Field Name="LocalizedTextValue" TypeName="ua:LocalizedText" /> // <opc:Field Name="StatusCodeValue" TypeName="ua:StatusCode" /> // <opc:Field Name="VariantValue" TypeName="ua:Variant" /> // <opc:Field Name="EnumerationValue" TypeName="ua:Int32" /> // <opc:Field Name="StructureValue" TypeName="ua:ExtensionObject" /> // <opc:Field Name="Number" TypeName="ua:Variant" /> // <opc:Field Name="Integer" TypeName="ua:Variant" /> // <opc:Field Name="UInteger" TypeName="ua:Variant" /> // </opc:StructuredType> // // <opc:StructuredType Name="ArrayValueDataType" BaseType="ua:ExtensionObject"> // <opc:Field Name="NoOfBooleanValue" TypeName="opc:Int32" /> // <opc:Field Name="BooleanValue" TypeName="opc:Boolean" LengthField="NoOfBooleanValue" /> // <opc:Field Name="NoOfSByteValue" TypeName="opc:Int32" /> } } }
# Shows how to obtain data type description object for complex data node with OPC UA Complex Data plug-in, and the # actual content of the data type dictionary. # # Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html . # OPC client and subscriber examples in Python on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-Python . # The QuickOPC package is needed. Install it using "pip install opclabs_quickopc". import opclabs_quickopc # Import .NET namespaces. from Microsoft.Extensions.DependencyInjection import * from System import * from System.Text import * from OpcLabs.EasyOpc.UA import * from OpcLabs.EasyOpc.UA.AddressSpace import * from OpcLabs.EasyOpc.UA.AddressSpace.Standard import * from OpcLabs.EasyOpc.UA.DataTypeModel.Extensions import * #from OpcLabs.EasyOpc.UA.Extensions import * from OpcLabs.EasyOpc.UA.InformationModel import * from OpcLabs.EasyOpc.UA.Plugins.ComplexData import * endpointDescriptor = UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:51210/UA/SampleServer') # or 'http://opcua.demo-this.com:51211/UA/SampleServer' (currently not supported) # or 'https://opcua.demo-this.com:51212/UA/SampleServer/' # Instantiate the client object. client = EasyUAClient() # Obtain the data type ID. # # In many cases, you would be able to obtain the data type ID of a particular node by reading its DataType # attribute, or easier, by calling the extension method ReadDataType on the IEasyUAClient interface. # The sample server, however, shows a more advanced approach in which the data type ID refers to an abstract # data type, and the actual values are then sub-types of this base data type. This abstract data type does not # have any encodings associated with it and it is therefore not possible to extract its description from the # server. We therefore use a hard-coded data type ID for one of the sub-types in this example. # # The code to obtain the data type ID for given node would normally look like this: # dataTypeId = IEasyUAClientExtension2.ReadDataType(client, # endpointDescriptor, # UANodeDescriptor('nsu=http://test.org/UA/Data/ ;i=10239')) # [ObjectsFolder]/Data.Static.Scalar.StructureValue dataTypeId = UANodeId('nsu=http://test.org/UA/Data/ ;i=9440') # ScalarValueDataType # Get the IEasyUAClientComplexData service from the client. This is needed for advanced complex data # operations. complexData = ServiceProviderServiceExtensions.GetService[IEasyUAClientComplexData](client) if complexData is None: print('The client complex data service is not available.') exit() # Get the data type model provider. Provides methods to access data types in OPC UA model. dataTypeModelProvider = complexData.DataTypeModelProvider # Resolve the data type ID from our data type ID, for encoding name "Default Binary". encodingIdResult = IUADataTypeModelProviderExtension.ResolveEncodingIdFromDataTypeId(dataTypeModelProvider, UAModelNodeDescriptor(endpointDescriptor, UANodeDescriptor(dataTypeId)), UABrowseNames.DefaultBinary) # Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown. if not encodingIdResult.Succeeded: print('*** Failure: ', encodingIdResult.ErrorMessageBrief) exit() encodingId = encodingIdResult.Value # Get the data type dictionary provider. Provides methods to access data type dictionaries in OPC UA model. dataTypeDictionaryProvider = complexData.DataTypeDictionaryProvider # Resolve the data type descriptor from the encoding ID. dataTypeDescriptorResult = IUADataTypeDictionaryProviderExtension.ResolveDataTypeDescriptorFromDataTypeEncodingId( dataTypeDictionaryProvider, encodingId) # Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown. if not dataTypeDescriptorResult.Succeeded: print('*** Failure: ', dataTypeDescriptorResult.ErrorMessageBrief) exit() dataTypeDescriptor = dataTypeDescriptorResult.Value # The data type descriptor contains two pieces of information: # The data type dictionary ID: This determines the dictionary where the data type is defined. print(dataTypeDescriptor.DataTypeDictionaryId) # And the data type description: It is a "pointer" into the data type dictionary itself, selecting a specific # type definition inside the data type dictionary. The format of it depends on the data type system; # in our case, it is a string that is the name of one of the type elements in the XML document of the data type # dictionary. print(dataTypeDescriptor.DataTypeDescription) # Obtain the actual content of the data type dictionary. dataTypeDictionaryResult = IUADataTypeDictionaryProviderExtension.GetDataTypeDictionaryFromDataTypeDictionaryId( dataTypeDictionaryProvider, dataTypeDescriptor.DataTypeDictionaryId) # Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown. if not dataTypeDictionaryResult.Succeeded: print('*** Failure: ', dataTypeDictionaryResult.ErrorMessageBrief) exit() dataTypeDictionary = dataTypeDictionaryResult.Value # The data type dictionary returned is an array of bytes; its syntax and semantics depends on the data type # system. In our case, we know that the data type dictionary is actually a string encoded in UTF-8. text = Encoding.UTF8.GetString(dataTypeDictionary) print() print(text) print() print('Finished.')
' Shows how to obtain data type description object for complex data node with OPC UA Complex Data plug-in, and the actual ' content of the data type dictionary. ' ' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html . Imports System Imports System.Text Imports Microsoft.Extensions.DependencyInjection Imports OpcLabs.BaseLib.OperationModel.Generic Imports OpcLabs.EasyOpc.UA Imports OpcLabs.EasyOpc.UA.AddressSpace Imports OpcLabs.EasyOpc.UA.AddressSpace.Standard Imports OpcLabs.EasyOpc.UA.DataTypeModel Imports OpcLabs.EasyOpc.UA.DataTypeModel.Extensions Imports OpcLabs.EasyOpc.UA.InformationModel Imports OpcLabs.EasyOpc.UA.Plugins.ComplexData Namespace ComplexData._IUADataTypeDictionaryProvider Friend Class ResolveDataTypeDescriptorFromDataTypeEncodingId Public Shared Sub Main1() ' Define which server we will work with. Dim endpointDescriptor As UAEndpointDescriptor = "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer" ' or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported) ' or "https://opcua.demo-this.com:51212/UA/SampleServer/" ' Instantiate the client object. Dim client = New EasyUAClient ' Obtain the data type ID. ' ' In many cases, you would be able to obtain the data type ID of a particular node by reading its DataType ' attribute, or easier, by calling the extension method ReadDataType on the IEasyUAClient interface. The sample ' server, however, shows a more advanced approach in which the data type ID refers to an abstract data type, ' and the actual values are then sub-types of this base data type. This abstract data type does not have any ' encodings associated with it and it is therefore not possible to extract its description from the server. ' We therefore use a hard-coded data type ID for one of the sub-types in this example. ' ' The code to obtain the data type ID for given node would normally look like this: ' UANodeId dataTypeId = client.ReadDataType( ' endpointUriString, ' "nsu=http://test.org/UA/Data/ ;i=10239"); // [ObjectsFolder]/Data.Static.Scalar.StructureValue ' Dim dataTypeId As UANodeId = "nsu=http://test.org/UA/Data/ ;i=9440" ' ScalarValueDataType ' Get the IEasyUAClientComplexData service from the client. This is needed for advanced complex data ' operations. Dim complexData As IEasyUAClientComplexData = client.GetService(Of IEasyUAClientComplexData) ' Get the data type model provider. Provides methods to access data types in OPC UA model. Dim dataTypeModelProvider As IUADataTypeModelProvider = complexData.DataTypeModelProvider ' Resolve the data type ID from our data type ID, for encoding name "Default Binary". Dim encodingIdResult As ValueResult(Of UAModelNodeDescriptor) = dataTypeModelProvider.ResolveEncodingIdFromDataTypeId( New UAModelNodeDescriptor(endpointDescriptor, dataTypeId), UABrowseNames.DefaultBinary) ' Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown. If Not encodingIdResult.Succeeded Then Console.WriteLine("*** Failure: {0}", encodingIdResult.ErrorMessageBrief) Exit Sub End If Dim encodingId As UAModelNodeDescriptor = encodingIdResult.Value ' Get the data type dictionary provider. Provides methods to access data type dictionaries in OPC UA model. Dim dataTypeDictionaryProvider As IUADataTypeDictionaryProvider = complexData.DataTypeDictionaryProvider ' Resolve the data type descriptor from the encoding ID. Dim dataTypeDescriptorResult As ValueResult(Of UADataTypeDescriptor) = dataTypeDictionaryProvider.ResolveDataTypeDescriptorFromDataTypeEncodingId(encodingId) ' Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown. If Not dataTypeDescriptorResult.Succeeded Then Console.WriteLine("*** Failure: {0}", dataTypeDescriptorResult.ErrorMessageBrief) Exit Sub End If Dim dataTypeDescriptor As UADataTypeDescriptor = dataTypeDescriptorResult.Value ' The data type descriptor contains two pieces of information: ' The data type dictionary ID: This determines the dictionary where the data type is defined. Console.WriteLine(dataTypeDescriptor.DataTypeDictionaryId) ' And the data type description: It is a "pointer" into the data type dictionary itself, selecting a specific ' type definition inside the data type dictionary. The format of it depends on the data type system; ' in our case, it is a string that is the name of one of the type elements in the XML document of the data type ' dictionary. Console.WriteLine(dataTypeDescriptor.DataTypeDescription) ' Obtain the actual content of the data type dictionary. Dim dataTypeDictionaryResult As ValueResult(Of Byte()) = dataTypeDictionaryProvider.GetDataTypeDictionaryFromDataTypeDictionaryId(dataTypeDescriptor.DataTypeDictionaryId) ' Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown. If Not dataTypeDictionaryResult.Succeeded Then Console.WriteLine("*** Failure: {0}", dataTypeDictionaryResult.ErrorMessageBrief) Exit Sub End If Dim dataTypeDictionary() As Byte = dataTypeDictionaryResult.Value ' The data type dictionary returned is an array of bytes; its syntax and semantics depends on the data type ' system. In our case, we know that the data type dictionary is actually a string encoded in UTF-8. Dim text As String = Encoding.UTF8.GetString(dataTypeDictionary) Console.WriteLine() Console.WriteLine(text) ' Example output (truncated): ' 'http://opcua.demo-this.com:51211/UA/SampleServer; NodeId="nsu=http://test.org/UA/Data/ ;ns=2;i=11422" 'ScalarValueDataType ' '<opc:TypeDictionary ' xmlns:opc="http://opcfoundation.org/BinarySchema/" ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' xmlns:ua="http://opcfoundation.org/UA/" ' xmlns:tns="http://test.org/UA/Data/" ' DefaultByteOrder="LittleEndian" ' TargetNamespace="http://test.org/UA/Data/" '> ' <!-- This File was generated on 2013-01-22 and supports the specifications supported by version 1.1.334.0 of the OPC UA deliverables. --> ' <opc:Import Namespace="http://opcfoundation.org/UA/" Location="Opc.Ua.BinarySchema.bsd"/> ' ' <opc:StructuredType Name="ScalarValueDataType" BaseType="ua:ExtensionObject"> ' <opc:Field Name="BooleanValue" TypeName="opc:Boolean" /> ' <opc:Field Name="SByteValue" TypeName="opc:SByte" /> ' <opc:Field Name="ByteValue" TypeName="opc:Byte" /> ' <opc:Field Name="Int16Value" TypeName="opc:Int16" /> ' <opc:Field Name="UInt16Value" TypeName="opc:UInt16" /> ' <opc:Field Name="Int32Value" TypeName="opc:Int32" /> ' <opc:Field Name="UInt32Value" TypeName="opc:UInt32" /> ' <opc:Field Name="Int64Value" TypeName="opc:Int64" /> ' <opc:Field Name="UInt64Value" TypeName="opc:UInt64" /> ' <opc:Field Name="FloatValue" TypeName="opc:Float" /> ' <opc:Field Name="DoubleValue" TypeName="opc:Double" /> ' <opc:Field Name="StringValue" TypeName="opc:String" /> ' <opc:Field Name="DateTimeValue" TypeName="opc:DateTime" /> ' <opc:Field Name="GuidValue" TypeName="opc:Guid" /> ' <opc:Field Name="ByteStringValue" TypeName="opc:ByteString" /> ' <opc:Field Name="XmlElementValue" TypeName="ua:XmlElement" /> ' <opc:Field Name="NodeIdValue" TypeName="ua:NodeId" /> ' <opc:Field Name="ExpandedNodeIdValue" TypeName="ua:ExpandedNodeId" /> ' <opc:Field Name="QualifiedNameValue" TypeName="ua:QualifiedName" /> ' <opc:Field Name="LocalizedTextValue" TypeName="ua:LocalizedText" /> ' <opc:Field Name="StatusCodeValue" TypeName="ua:StatusCode" /> ' <opc:Field Name="VariantValue" TypeName="ua:Variant" /> ' <opc:Field Name="EnumerationValue" TypeName="ua:Int32" /> ' <opc:Field Name="StructureValue" TypeName="ua:ExtensionObject" /> ' <opc:Field Name="Number" TypeName="ua:Variant" /> ' <opc:Field Name="Integer" TypeName="ua:Variant" /> ' <opc:Field Name="UInteger" TypeName="ua:Variant" /> ' </opc:StructuredType> ' ' <opc:StructuredType Name="ArrayValueDataType" BaseType="ua:ExtensionObject"> ' <opc:Field Name="NoOfBooleanValue" TypeName="opc:Int32" /> ' <opc:Field Name="BooleanValue" TypeName="opc:Boolean" LengthField="NoOfBooleanValue" /> ' <opc:Field Name="NoOfSByteValue" TypeName="opc:Int32" /> End Sub End Class End Namespace
// Shows how to obtain data type description object for complex data node with OPC UA Complex Data plug-in, and the actual // content of the data type dictionary. // // Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html . class procedure ResolveDataTypeDescriptorFromDataTypeEncodingId.Main; var Client: _EasyUAClient; ComplexData: _EasyUAClientComplexData; DataTypeDictionary: OleVariant; DataTypeDictionaryResult: _ValueResult; DataTypeDescriptor: _UADataTypeDescriptor; DataTypeDescriptorResult: _ValueResult; DataTypeId: string; DataTypeModelProvider: _UADataTypeModelProvider; DataTypeDictionaryProvider: _UADataTypeDictionaryProvider; EncodingId: _UAModelNodeDescriptor; EncodingIdResult: _ValueResult; EncodingName: _UAQualifiedName; EndpointDescriptor: string; I: Cardinal; ModelNodeDescriptor: _UAModelNodeDescriptor; Text: string; begin // Define which server and node we will work with. EndpointDescriptor := 'http://opcua.demo-this.com:51211/UA/SampleServer'; //or 'https://opcua.demo-this.com:51212/UA/SampleServer/'; //or 'opc.tcp://opcua.demo-this.com:51210/UA/SampleServer'; // Instantiate the client object Client := CoEasyUAClient.Create; // Obtain the data type ID. // // In many cases, you would be able to obtain the data type ID of a particular node by reading its DataType // attribute. // The sample server, however, shows a more advanced approach in which the data type ID refers to an abstract data type, and // the actual values are then sub-types of this base data type. This abstract data type does not have any encodings // associated with it and it is therefore not possible to extract its description from the server. We therefore use // a hard-coded data type ID for one of the sub-types in this example. DataTypeId := 'nsu=http://test.org/UA/Data/ ;i=9440'; // ScalarValueDataType // Get the IEasyUAClientComplexData service from the client. This is needed for advanced complex data // operations. ComplexData := IInterface(Client.GetServiceByName('OpcLabs.EasyOpc.UA.Plugins.ComplexData.IEasyUAClientComplexData, OpcLabs.EasyOpcUA')) as _EasyUAClientComplexData; // Get the data type model provider. Provides methods to access data types in OPC UA model. DataTypeModelProvider := ComplexData.DataTypeModelProvider; // Resolve the data type ID from our data type ID, for encoding name "Default Binary". ModelNodeDescriptor := CoUAModelNodeDescriptor.Create; ModelNodeDescriptor.EndpointDescriptor.UrlString := EndpointDescriptor; ModelNodeDescriptor.NodeDescriptor.NodeId.ExpandedText := DataTypeId; EncodingName := CoUAQualifiedName.Create; EncodingName.StandardName := 'DefaultBinary'; EncodingIdResult := DataTypeModelProvider.ResolveEncodingIdFromDataTypeId(ModelNodeDescriptor, EncodingName); // Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown. if not EncodingIdResult.Succeeded then begin WriteLn(Format('*** Failure: %s', [EncodingIdResult.ErrorMessageBrief])); Exit; end; EncodingId := IUnknown(EncodingIdResult.Value) as _UAModelNodeDescriptor; // Get the data type dictionary provider. Provides methods to access data type dictionaries in OPC UA model. DataTypeDictionaryProvider := ComplexData.DataTypeDictionaryProvider; // Resolve the data type descriptor from the encoding ID. DataTypeDescriptorResult := DataTypeDictionaryProvider.ResolveDataTypeDescriptorFromDataTypeEncodingId(EncodingId); // Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown. if not DataTypeDescriptorResult.Succeeded then begin WriteLn(Format('*** Failure: %s', [DataTypeDescriptorResult.ErrorMessageBrief])); Exit; end; DataTypeDescriptor := IUnknown(DataTypeDescriptorResult.Value) as _UADataTypeDescriptor; // The data type descriptor contains two pieces of information: // The data type dictionary ID: This determines the dictionary where the data type is defined. WriteLn(DataTypeDescriptor.DataTypeDictionaryId.ToString); // And the data type description: It is a "pointer" into the data type dictionary itself, selecting a specific // type definition inside the data type dictionary. The format of it depends on the data type system; // in our case, it is a string that is the name of one of the type elements in the XML document of the data type // dictionary. WriteLn(DataTypeDescriptor.DataTypeDescription); // Obtain the actual content of the data type dictionary. DataTypeDictionaryResult := DataTypeDictionaryProvider.GetDataTypeDictionaryFromDataTypeDictionaryId(DataTypeDescriptor.DataTypeDictionaryId); // Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown. if not DataTypeDictionaryResult.Succeeded then begin WriteLn(Format('*** Failure: %s', [DataTypeDictionaryResult.ErrorMessageBrief])); Exit; end; DataTypeDictionary := DataTypeDictionaryResult.Value; // The data type dictionary returned is an array of bytes; its syntax and semantics depends on the data type // system. In our case, we know that the data type dictionary is actually a string encoded in UTF-8. for I := VarArrayLowBound(DataTypeDictionary, 1) to VarArrayHighBound(DataTypeDictionary, 1) do begin Text := Text + Chr(Byte(DataTypeDictionary[I])); end; WriteLn; WriteLn(Text); // Example output (truncated): // //http://opcua.demo-this.com:51211/UA/SampleServer; NodeId="nsu=http://test.org/UA/Data/ ;ns=2;i=11422" //ScalarValueDataType // //<opc:TypeDictionary // xmlns:opc="http://opcfoundation.org/BinarySchema/" // xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" // xmlns:ua="http://opcfoundation.org/UA/" // xmlns:tns="http://test.org/UA/Data/" // DefaultByteOrder="LittleEndian" // TargetNamespace="http://test.org/UA/Data/" //> // <!-- This File was generated on 2013-01-22 and supports the specifications supported by version 1.1.334.0 of the OPC UA deliverables. --> // <opc:Import Namespace="http://opcfoundation.org/UA/" Location="Opc.Ua.BinarySchema.bsd"/> // // <opc:StructuredType Name="ScalarValueDataType" BaseType="ua:ExtensionObject"> // <opc:Field Name="BooleanValue" TypeName="opc:Boolean" /> // <opc:Field Name="SByteValue" TypeName="opc:SByte" /> // <opc:Field Name="ByteValue" TypeName="opc:Byte" /> // <opc:Field Name="Int16Value" TypeName="opc:Int16" /> // <opc:Field Name="UInt16Value" TypeName="opc:UInt16" /> // <opc:Field Name="Int32Value" TypeName="opc:Int32" /> // <opc:Field Name="UInt32Value" TypeName="opc:UInt32" /> // <opc:Field Name="Int64Value" TypeName="opc:Int64" /> // <opc:Field Name="UInt64Value" TypeName="opc:UInt64" /> // <opc:Field Name="FloatValue" TypeName="opc:Float" /> // <opc:Field Name="DoubleValue" TypeName="opc:Double" /> // <opc:Field Name="StringValue" TypeName="opc:String" /> // <opc:Field Name="DateTimeValue" TypeName="opc:DateTime" /> // <opc:Field Name="GuidValue" TypeName="opc:Guid" /> // <opc:Field Name="ByteStringValue" TypeName="opc:ByteString" /> // <opc:Field Name="XmlElementValue" TypeName="ua:XmlElement" /> // <opc:Field Name="NodeIdValue" TypeName="ua:NodeId" /> // <opc:Field Name="ExpandedNodeIdValue" TypeName="ua:ExpandedNodeId" /> // <opc:Field Name="QualifiedNameValue" TypeName="ua:QualifiedName" /> // <opc:Field Name="LocalizedTextValue" TypeName="ua:LocalizedText" /> // <opc:Field Name="StatusCodeValue" TypeName="ua:StatusCode" /> // <opc:Field Name="VariantValue" TypeName="ua:Variant" /> // <opc:Field Name="EnumerationValue" TypeName="ua:Int32" /> // <opc:Field Name="StructureValue" TypeName="ua:ExtensionObject" /> // <opc:Field Name="Number" TypeName="ua:Variant" /> // <opc:Field Name="Integer" TypeName="ua:Variant" /> // <opc:Field Name="UInteger" TypeName="ua:Variant" /> // </opc:StructuredType> // // <opc:StructuredType Name="ArrayValueDataType" BaseType="ua:ExtensionObject"> // <opc:Field Name="NoOfBooleanValue" TypeName="opc:Int32" /> // <opc:Field Name="BooleanValue" TypeName="opc:Boolean" LengthField="NoOfBooleanValue" /> // <opc:Field Name="NoOfSByteValue" TypeName="opc:Int32" /> end;
Rem Shows how to obtain data type description object for complex data node with OPC UA Complex Data plug-in, and the actual Rem content of the data type dictionary. Rem Rem Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html . Option Explicit ' Define which server we will work with. Dim endpointDescriptor: endpointDescriptor = _ "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer" '"http://opcua.demo-this.com:51211/UA/SampleServer" '"https://opcua.demo-this.com:51212/UA/SampleServer/" ' Instantiate the client object. Dim Client: Set Client = CreateObject("OpcLabs.EasyOpc.UA.EasyUAClient") ' Obtain the data type ID. ' ' In many cases, you would be able to obtain the data type ID of a particular node by reading its DataType ' attribute. ' The sample server, however, shows a more advanced approach in which the data type ID refers to an abstract data type, and ' the actual values are then sub-types of this base data type. This abstract data type does not have any encodings ' associated with it and it is therefore not possible to extract its description from the server. We therefore use ' a hard-coded data type ID for one of the sub-types in this example. Dim dataTypeId: dataTypeId = "nsu=http://test.org/UA/Data/ ;i=9440" ' ScalarValueDataType ' Get the IEasyUAClientComplexData service from the client. This is needed for advanced complex data ' operations. Dim ComplexData: Set ComplexData = _ Client.GetServiceByName("OpcLabs.EasyOpc.UA.Plugins.ComplexData.IEasyUAClientComplexData, OpcLabs.EasyOpcUA") ' Get the data type model provider. Provides methods to access data types in OPC UA model. Dim DataTypeModelProvider: Set DataTypeModelProvider = ComplexData.DataTypeModelProvider ' Resolve the data type ID from our data type ID, for encoding name "Default Binary". Dim ModelNodeDescriptor: Set ModelNodeDescriptor = CreateObject("OpcLabs.EasyOpc.UA.InformationModel.UAModelNodeDescriptor") ModelNodeDescriptor.EndpointDescriptor.UrlString = endpointDescriptor ModelNodeDescriptor.NodeDescriptor.NodeId.ExpandedText = dataTypeId Dim EncodingName: Set EncodingName = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UAQualifiedName") EncodingName.StandardName = "DefaultBinary" Dim EncodingIdResult: Set EncodingIdResult = _ DataTypeModelProvider.ResolveEncodingIdFromDataTypeId(ModelNodeDescriptor, EncodingName) ' Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown. If Not EncodingIdResult.Succeeded Then WScript.Echo "*** Failure: " & EncodingIdResult.Exception.GetBaseException().Message WScript.Quit End If Dim EncodingId: Set EncodingId = EncodingIdResult.Value ' Get the data type dictionary provider. Provides methods to access data type dictionaries in OPC UA model. Dim DataTypeDictionaryProvider: Set DataTypeDictionaryProvider = ComplexData.DataTypeDictionaryProvider ' Resolve the data type descriptor from the encoding ID. Dim DataTypeDescriptorResult: Set DataTypeDescriptorResult = _ DataTypeDictionaryProvider.ResolveDataTypeDescriptorFromDataTypeEncodingId(EncodingId) ' Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown. If Not DataTypeDescriptorResult.Succeeded Then WScript.Echo "*** Failure: " & DataTypeDescriptorResult.Exception.GetBaseException().Message WScript.Quit End If Dim DataTypeDescriptor: Set DataTypeDescriptor = DataTypeDescriptorResult.Value ' The data type descriptor contains two pieces of information: ' The data type dictionary ID: This determines the dictionary where the data type is defined. WScript.Echo DataTypeDescriptor.DataTypeDictionaryId ' And the data type description: It is a "pointer" into the data type dictionary itself, selecting a specific ' type definition inside the data type dictionary. The format of it depends on the data type system; ' in our case, it is a string that is the name of one of the type elements in the XML document of the data type ' dictionary. WScript.Echo DataTypeDescriptor.DataTypeDescription ' Obtain the actual content of the data type dictionary. Dim DataTypeDictionaryResult: Set DataTypeDictionaryResult = _ DataTypeDictionaryProvider.GetDataTypeDictionaryFromDataTypeDictionaryId(DataTypeDescriptor.DataTypeDictionaryId) ' Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown. If Not DataTypeDictionaryResult.Succeeded Then WScript.Echo "*** Failure: " & DataTypeDictionaryResult.Exception.GetBaseException().Message WScript.Quit End If Dim DataTypeDictionary: DataTypeDictionary = DataTypeDictionaryResult.Value ' The data type dictionary returned is an array of bytes; its syntax and semantics depends on the data type ' system. In our case, we know that the data type dictionary is actually a string encoded in UTF-8. Dim text Dim i: For i = LBound(DataTypeDictionary) To UBound(DataTypeDictionary) text = text & Chr(DataTypeDictionary(i)) Next WScript.Echo WScript.Echo text ' Example output (truncated): ' 'http://opcua.demo-this.com:51211/UA/SampleServer; NodeId="nsu=http:'test.org/UA/Data/;ns=2;i=11422" 'ScalarValueDataType ' '<opc:TypeDictionary ' xmlns:opc="http:'opcfoundation.org/BinarySchema/" ' xmlns:xsi="http:'www.w3.org/2001/XMLSchema-instance" ' xmlns:ua="http:'opcfoundation.org/UA/" ' xmlns:tns="http:'test.org/UA/Data/" ' DefaultByteOrder="LittleEndian" ' TargetNamespace="http:'test.org/UA/Data/" '> ' <!-- This File was generated on 2013-01-22 and supports the specifications supported by version 1.1.334.0 of the OPC UA deliverables. --> ' <opc:Import Namespace="http:'opcfoundation.org/UA/" Location="Opc.Ua.BinarySchema.bsd"/> ' ' <opc:StructuredType Name="ScalarValueDataType" BaseType="ua:ExtensionObject"> ' <opc:Field Name="BooleanValue" TypeName="opc:Boolean" /> ' <opc:Field Name="SByteValue" TypeName="opc:SByte" /> ' <opc:Field Name="ByteValue" TypeName="opc:Byte" /> ' <opc:Field Name="Int16Value" TypeName="opc:Int16" /> ' <opc:Field Name="UInt16Value" TypeName="opc:UInt16" /> ' <opc:Field Name="Int32Value" TypeName="opc:Int32" /> ' <opc:Field Name="UInt32Value" TypeName="opc:UInt32" /> ' <opc:Field Name="Int64Value" TypeName="opc:Int64" /> ' <opc:Field Name="UInt64Value" TypeName="opc:UInt64" /> ' <opc:Field Name="FloatValue" TypeName="opc:Float" /> ' <opc:Field Name="DoubleValue" TypeName="opc:Double" /> ' <opc:Field Name="StringValue" TypeName="opc:String" /> ' <opc:Field Name="DateTimeValue" TypeName="opc:DateTime" /> ' <opc:Field Name="GuidValue" TypeName="opc:Guid" /> ' <opc:Field Name="ByteStringValue" TypeName="opc:ByteString" /> ' <opc:Field Name="XmlElementValue" TypeName="ua:XmlElement" /> ' <opc:Field Name="NodeIdValue" TypeName="ua:NodeId" /> ' <opc:Field Name="ExpandedNodeIdValue" TypeName="ua:ExpandedNodeId" /> ' <opc:Field Name="QualifiedNameValue" TypeName="ua:QualifiedName" /> ' <opc:Field Name="LocalizedTextValue" TypeName="ua:LocalizedText" /> ' <opc:Field Name="StatusCodeValue" TypeName="ua:StatusCode" /> ' <opc:Field Name="VariantValue" TypeName="ua:Variant" /> ' <opc:Field Name="EnumerationValue" TypeName="ua:Int32" /> ' <opc:Field Name="StructureValue" TypeName="ua:ExtensionObject" /> ' <opc:Field Name="Number" TypeName="ua:Variant" /> ' <opc:Field Name="Integer" TypeName="ua:Variant" /> ' <opc:Field Name="UInteger" TypeName="ua:Variant" /> ' </opc:StructuredType> ' ' <opc:StructuredType Name="ArrayValueDataType" BaseType="ua:ExtensionObject"> ' <opc:Field Name="NoOfBooleanValue" TypeName="opc:Int32" /> ' <opc:Field Name="BooleanValue" TypeName="opc:Boolean" LengthField="NoOfBooleanValue" /> ' <opc:Field Name="NoOfSByteValue" TypeName="opc:Int32" />
Copyright © 2004-2024 CODE Consulting and Development, s.r.o., Plzen. All rights reserved. Web page: www.opclabs.com
Send Documentation Feedback. Resources: Knowledge Base, Product Downloads. Technical support: Online Forums, FAQ.Missing some example? Ask us for it on our Online Forums! You do not have to own a commercial license in order to use Online Forums, and we reply to every post.